﻿using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using K9Nano.LayIM;
using K9Nano.LayIM.Models;
using K9Nano.LayIM.Stores;
using Microsoft.Extensions.Options;
using WalkingTec.Mvvm.Core;

namespace K9Nano.IM.LayIM
{
    public class ChatFileStore : ChatStoreBase, IFileStore
    {
        private readonly string _root;

        public ChatFileStore(IDataContext db, IOptions<LayIMOptions> options) : base(db, options)
        {
            _root = GlobalServices.GetService<Configs>().FileUploadOptions.UploadDir;
        }

        public async Task<string> SaveAsync(string name, Stream stream, CancellationToken cancellation)
        {
            var attachment = new FileAttachment
            {
                FileName = name,
                FileExt = Path.GetExtension(name),
                SaveFileMode = SaveFileModeEnum.Local,
                Length = stream.Length,
                UploadTime = DateTime.Now
            };
            var path = GetCurrentPath();
            var filePath = Path.Combine(_root, path);
            Directory.CreateDirectory(filePath);
            var fileName = Guid.NewGuid() + attachment.FileExt;
            attachment.Path = Path.Combine(path, fileName);
            var fileFullPath = Path.Combine(_root, attachment.Path);

            await using var writer = File.OpenWrite(fileFullPath);
            await stream.CopyToAsync(writer, cancellation);
            Db.AddEntity(attachment);
            await Db.SaveChangesAsync(cancellation);
            return attachment.ID.ToString();
        }

        public async Task<LayIMFile> GetAsync(string id, CancellationToken cancellation)
        {
            Guid.TryParse(id, out var gid);
            var attachment = await Db.Set<FileAttachment>().FindAsync(gid);
            if (attachment == null) return null;

            var file = Path.Combine(_root, attachment.Path);
            if (File.Exists(file))
            {
                return new LayIMFile
                {
                    Name = attachment.FileName,
                    Stream = File.OpenRead(file)
                };
            }

            return null;
        }

        public async Task DeleteAsync(string id)
        {
            Guid.TryParse(id, out var gid);
            var attachment = await Db.Set<FileAttachment>().FindAsync(gid);
            if (attachment == null) return;

            var file = Path.Combine(_root, attachment.Path);
            if (File.Exists(file))
            {
                File.Delete(file);
            }
        }

        private string GetCurrentPath()
        {
            var path = Path.Combine(DateTime.Today.Year.ToString(),
                DateTime.Today.Month.ToString("00"),
                DateTime.Today.Day.ToString("00"));
            return path;
        }
    }
}